#include "LevelState.h"
#include "../GameObjects/BaseObject.h"
#include "../GameObjects/Map.h"
#include "../GameObjects/GamePiece.h"
#include "../TinyXML/tinyxml.h"
#include "../Wrapper/CSGD_TextureManager.h"
#include "../Wrapper/CSGD_DirectInput.h"
#include "../Wrapper/ObjectManager.h"
#include "../Game.h"

#include <string>
using std::string;

LevelState::LevelState()
{
	map = NULL;
	game = NULL;
	trackImageID = -1;
	outlineImageID = -1;
	currTile = -1;
	toggleRotate = false;
}

LevelState::~LevelState()
{

}

/* CORE FUNCTIONS */

void LevelState::Enter()
{
	game = Game::GetInstance();
	objManager = ObjectManager::GetInstance();
	texManager = CSGD_TextureManager::GetInstance();

	// Load the map
	LoadLevel("Resource/Data/Levels/TrainMap1024.xml");

	// Load textures
	trackImageID = texManager->LoadTexture("Resource/Graphics/HUD/TrackBase.jpg");
	cursorImageID = texManager->LoadTexture("Resource/Graphics/HUD/cursor.png");
	outlineImageID = texManager->LoadTexture("Resource/Graphics/HUD/piece_outline.png");

	// TEMPORARY
	tempRect.left = 150;
	tempRect.top = 650;
	tempRect.right = tempRect.left + 64;
	tempRect.bottom = tempRect.top + 64;
}

bool LevelState::Input()
{
	if (CSGD_DirectInput::GetInstance()->MouseButtonPressed(1))
	{
		toggleRotate = !toggleRotate;
	}

	if (CSGD_DirectInput::GetInstance()->MouseButtonPressed(0))
	{
		if (game->GetCursorPosition().x > tempRect.left && game->GetCursorPosition().x < tempRect.right &&
			game->GetCursorPosition().y > tempRect.top && game->GetCursorPosition().y < tempRect.bottom)
		{
			currTile = 1;
		}
		else if (game->GetCursorPosition().y < 576 && currTile != -1)
		{
			GamePiece* newTrack = new GamePiece(PIECE_TRACK_STRAIGHT, true);
			newTrack->SetPositionX((game->GetCursorPosition().x / TILE_SIZE) * TILE_SIZE);
			newTrack->SetPositionY((game->GetCursorPosition().y / TILE_SIZE) * TILE_SIZE);
			if (toggleRotate)
				newTrack->SetRotation(90.0f);

			objManager->AddObject(newTrack);
		}
	}

	if (CSGD_DirectInput::GetInstance()->KeyPressed(DIK_SPACE))
	{
		currTile = -1;
	}

	return true;
}

void LevelState::Update(float _dT)
{

}

void LevelState::Render()
{
	// Map
	map->Render();

	// Track backdrop
	texManager->Draw(trackImageID, 0, 640);

	CSGD_Direct3D::GetInstance()->GetSprite()->Flush();

	// TEMPORARY
	CSGD_Direct3D::GetInstance()->DrawRect(tempRect, 255, 0, 0);

	if (currTile != -1)
	{
		//texManager->Draw(outlineImageID, tileLoc[currTile].x, tileLoc[currTile].y);
		texManager->Draw(outlineImageID, tempRect.left, tempRect.top);
	}

	objManager->RenderObjects();

	// Cursor
	texManager->Draw(cursorImageID, game->GetCursorPosition().x, game->GetCursorPosition().y, 0.25f, 0.25f);
}

void LevelState::Exit()
{

}

/* HELPER FUNCTIONS */
bool LevelState::LoadLevel(const char* _fileName)
{
	TiXmlDocument doc;
	if(!doc.LoadFile(_fileName))
		return false;

	TiXmlElement* root = doc.RootElement();
	if(!root)
		return false;

	TiXmlElement* tileLayer = root->FirstChildElement("TileLayer");
	if(tileLayer)
	{
		TiXmlElement* mapSize = tileLayer->FirstChildElement("MapSize");
		if(mapSize)
		{
			TiXmlElement* mapWidth = mapSize->FirstChildElement("MapWidth");
			TiXmlElement* mapHeight = mapSize->FirstChildElement("MapHeight");
			TiXmlElement* tileWidth = mapSize->FirstChildElement("MapTileWidth");
			TiXmlElement* tileHeight = mapSize->FirstChildElement("MapTileHeight");

			if(mapWidth && mapHeight && tileWidth && tileHeight)
			{
				int mWidth = atoi(mapWidth->GetText());
				int mHeight = atoi(mapHeight->GetText());
				int tWidth = atoi(tileWidth->GetText());
				int tHeight = atoi(tileHeight->GetText());
				
				map = new Map();
				map->SetDimensions(mWidth, mHeight, tWidth, tHeight);
			}
		}

		TiXmlElement* tilesets = tileLayer->FirstChildElement("Tilesets");
		if(tilesets)
		{
			TiXmlElement* set = tilesets->FirstChildElement("Tileset");

			while(set)
			{
				TiXmlElement* fileName = set->FirstChildElement("FileName");
				TiXmlElement* tileWidth = set->FirstChildElement("TileWidth");
				TiXmlElement* tileHeight = set->FirstChildElement("TileHeight");
				TiXmlElement* tileSetWidth = set->FirstChildElement("TilesetWidth");
				TiXmlElement* tileSetHeight = set->FirstChildElement("TilesetHeight");

				if( fileName && tileWidth && tileHeight && tileSetWidth && tileSetHeight)
				{
					const char* setFileName = fileName->GetText();
					short tWidth = atoi(tileWidth->GetText());
					short tHeight = atoi(tileHeight->GetText());
					short setWidth = atoi(tileSetWidth->GetText());
					short setHeight = atoi(tileSetHeight->GetText());

					string filePath = "Resource\\";
					filePath += setFileName;

					map->LoadTileset(filePath.c_str(), setWidth, setHeight, tWidth, tHeight);
				}		
				
				set = set->NextSiblingElement("Tileset");				
			}
		}

		TiXmlElement* coords = tileLayer->FirstChildElement("Coordinates");
		if(coords)
		{
			TiXmlElement* coord = coords->FirstChildElement("XY");

			while(coord)
			{
				TiXmlElement* xCoord = coord->FirstChildElement("xCoordinate");
				TiXmlElement* yCoord = coord->FirstChildElement("yCoordinate");
				TiXmlElement* tilesetID = coord->FirstChildElement("TilesetID");

				if(xCoord && yCoord && tilesetID)
				{
					int x = atoi(xCoord->GetText());
					int y = atoi(yCoord->GetText());
					int id = atoi(tilesetID->GetText());

					map->LoadTile(x,y,id);
				}

				coord = coord->NextSiblingElement("XY");	
			}
		}
	}

	TiXmlElement* objectLayer = root->FirstChildElement("ObjectLayer");
	if(objectLayer)
	{
		TiXmlElement* props = objectLayer->FirstChildElement("Props");
		if(props)
		{
			TiXmlElement* prop = props->FirstChildElement("Prop");

			while(prop)
			{
				TiXmlElement* fileName = prop->FirstChildElement("FileName");
				TiXmlElement* propWidth = prop->FirstChildElement("Width");
				TiXmlElement* propHeight = prop->FirstChildElement("Height");
				TiXmlElement* propX = prop->FirstChildElement("PositionX");
				TiXmlElement* propY = prop->FirstChildElement("PositionY");
				TiXmlElement* rot = prop->FirstChildElement("Rotation");

				if( fileName && propWidth && propHeight && propX && propY && rot)
				{
					const char* setFileName = fileName->GetText();
					int width = atoi(propWidth->GetText());
					int height = atoi(propHeight->GetText());
					int posX = atoi(propX->GetText());
					int posY = atoi(propY->GetText());
					int rotation = atoi( rot->GetText());
					
					string filePath = "Resource\\";
					filePath += setFileName;

					BaseObject* tempObj = new BaseObject();
					tempObj->SetWidth((float)width);
					tempObj->SetHeight((float)height);
					tempObj->SetPositionX((float)posX);
					tempObj->SetPositionY((float)posY);
					tempObj->SetRotation((float)rotation);
					tempObj->SetImageID(CSGD_TextureManager::GetInstance()->LoadTexture(filePath.c_str()));

					ObjectManager::GetInstance()->AddStaticObject(tempObj);
				}	

				prop = prop->NextSiblingElement("Prop");
			}
		}

		TiXmlElement* enemies = objectLayer->FirstChildElement("Enemies");

		if(enemies)
		{
			TiXmlElement* enemy = enemies->FirstChildElement("Enemy");

			while(enemy)
			{
				TiXmlElement* name = enemy->FirstChildElement("Name");
				TiXmlElement* posX = enemy->FirstChildElement("PositionX");
				TiXmlElement* posY = enemy->FirstChildElement("PositionY");

				if( name && posX && posY )
					string enemyType = name->GetText();

				enemy = enemy->NextSiblingElement("Enemy");
			}
		}

		TiXmlElement* powerups = objectLayer->FirstChildElement("Powerups");

		if(powerups)
		{
			TiXmlElement* powerup = powerups->FirstChildElement("Powerup");

			while(powerup)
			{
				TiXmlElement* name = powerup->FirstChildElement("Name");
				TiXmlElement* posX = powerup->FirstChildElement("PositionX");
				TiXmlElement* posY = powerup->FirstChildElement("PositionY");

				if(name && posX && posY)
				{
					string powerupType = name->GetText();

					//if(powerupType == "Health")
					//{
					//	MessageSystem::GetInstance()->SendMsg(new CreatePowerUpMessage((float)atof(posX->GetText()),(float)atof(posY->GetText()),POWERUP_HEALTH));
					//}
					//else if(powerupType == "Small Ammo")
					//{
					//	MessageSystem::GetInstance()->SendMsg(new CreatePowerUpMessage((float)atof(posX->GetText()),(float)atof(posY->GetText()),POWERUP_AMMO));
					//}

					powerup = powerup->NextSiblingElement("Powerup");
				}
			}
		}
	}

	TiXmlElement* triggerLayer = root->FirstChildElement("TriggerLayer");
		
	if(triggerLayer)
	{
		TiXmlElement* eventTriggers = triggerLayer->FirstChildElement("EventTriggers");
			
		if(eventTriggers)
		{
			TiXmlElement* events = eventTriggers->FirstChildElement("Event");

			while(events)
			{
				TiXmlElement* name = events->FirstChildElement("EventName");
				TiXmlElement* posX = events->FirstChildElement("PositionX");
				TiXmlElement* posY = events->FirstChildElement("PositionY");
				TiXmlElement* width = events->FirstChildElement("Width");
				TiXmlElement* height = events->FirstChildElement("Height");
				TiXmlElement* texID = events->FirstChildElement("ID");

				if(posX && posY && width && height && texID)
				{
					short x = atoi(posX->GetText());
					short y = atoi(posY->GetText());
					short w = atoi(width->GetText());
					short h = atoi(height->GetText());
					short id = atoi(texID->GetText());
					string eveName = name->GetText();

					//Trigger* temp = new Trigger(id, x, y, w, h, TRIG_EVENT, true, eveName);

					//ObjectManager::GetInstance()->AddTrigger(temp);

					//if (eveName == "Win")
					//{
					//	game->SetEndLevelPosX((float)(x + (w * 0.5f)));
					//	game->SetEndLevelPosY((float)(y + h));
					//}
				}

				events = events->NextSiblingElement("Event");
			}
		}

		TiXmlElement* collisionTriggers = triggerLayer->FirstChildElement("CollisionTriggers");

		if(collisionTriggers)
		{
			TiXmlElement* collision = collisionTriggers->FirstChildElement("Collision");

			while(collision)
			{
				TiXmlElement* posX = collision->FirstChildElement("PositionX");
				TiXmlElement* posY = collision->FirstChildElement("PositionY");
				TiXmlElement* width = collision->FirstChildElement("Width");
				TiXmlElement* height = collision->FirstChildElement("Height");
				TiXmlElement* texID = collision->FirstChildElement("ID");

				//if(posX && posY && width && height && texID)
				//{
				//	int x = atoi(posX->GetText());
				//	int y = atoi(posY->GetText());
				//	int w = atoi(width->GetText());
				//	int h = atoi(height->GetText());
				//	int id = atoi(texID->GetText());

				//	Trigger* temp = new Trigger(id, x, y, w, h, TRIG_COLLISION, true);

				//	ObjectManager::GetInstance()->AddTrigger(temp);
				//}

				collision = collision->NextSiblingElement("Collision");
			}
		}

		TiXmlElement* spawnTriggers = triggerLayer->FirstChildElement("SpawnTriggers");

		if(spawnTriggers)
		{
			TiXmlElement* spawn = spawnTriggers->FirstChildElement("Spawn");

			while(spawn)
			{
				TiXmlElement* name = spawn->FirstChildElement("EventName");
				TiXmlElement* posX = spawn->FirstChildElement("PositionX");
				TiXmlElement* posY = spawn->FirstChildElement("PositionY");
				TiXmlElement* width = spawn->FirstChildElement("Width");
				TiXmlElement* height = spawn->FirstChildElement("Height");
				TiXmlElement* texID = spawn->FirstChildElement("ID");
				TiXmlElement* spawnPosX = spawn->FirstChildElement("SpawnPointX");
				TiXmlElement* spawnPosY = spawn->FirstChildElement("SpawnPointY");

				if(posX && posY && width && height && texID && spawnPosX && spawnPosY && name)
				{
					string spawnType = name->GetText();
					int x = atoi(posX->GetText());
					int y = atoi(posY->GetText());
					int w = atoi(width->GetText());
					int h = atoi(height->GetText());
					int id = atoi(texID->GetText());

					/*Trigger* temp = new Trigger(id, x, y, w, h, TRIG_SPAWN, true);

					int spawnX = atoi(spawnPosX->GetText());
					int spawnY = atoi(spawnPosY->GetText());

					ObjectManager::GetInstance()->AddTrigger(temp);

					SpawnPoint* sp = new SpawnPoint(spawnX, spawnY, id);

					if(spawnType == "Tutorial")
					{
						sp->LoadSpawns("Resource\\Data\\Spawn\\tutorialspawn.xml");
					}
					else if(spawnType == "Ravager")
					{
						sp->LoadSpawns("Resource\\Data\\Spawn\\ravagerspawn.xml");
					}
					else if(spawnType == "Puffer")
					{
						sp->LoadSpawns("Resource\\Data\\Spawn\\pufferspawn.xml");
					}
					else if(spawnType == "Bruiser")
					{
						sp->LoadSpawns("Resource\\Data\\Spawn\\bruiserspawn.xml");
					}
					else if(spawnType == "Floater")
					{
						sp->LoadSpawns("Resource\\Data\\Spawn\\floaterspawn.xml");
					}

					enemySpawnpoints.push_back(sp);*/
				}

				spawn = spawn->NextSiblingElement("Spawn");
			}
		}

		TiXmlElement* playerSpawns = triggerLayer->FirstChildElement("PlayerSpawns");

		if(playerSpawns)
		{
			TiXmlElement* spawn = playerSpawns->FirstChildElement("Spawn");

			int i = 0;

			while(spawn)
			{
				TiXmlElement* posX = spawn->FirstChildElement("PositionX");
				TiXmlElement* posY = spawn->FirstChildElement("PositionY");

				if(posX && posY)
				{
					//if(i < 4)
					//{
					//	playerSpawnpoints[i].positionX = atoi(posX->GetText());
					//	playerSpawnpoints[i].positionY = atoi(posY->GetText());
					//}
					++i;
				}

				spawn = spawn->NextSiblingElement("Spawn");
			}
		}
	}

	TiXmlElement* lightLayer = root->FirstChildElement("LightLayer");

	if(lightLayer)
	{
		TiXmlElement* lights = lightLayer->FirstChildElement("Lights");

		if(lights)
		{
			TiXmlElement* light = lights->FirstChildElement("Light");

			while(light)
			{
				TiXmlElement* colorR = light->FirstChildElement("Red");
				TiXmlElement* colorG = light->FirstChildElement("Green");
				TiXmlElement* colorB = light->FirstChildElement("Blue");
				TiXmlElement* positionX = light->FirstChildElement("PositionX");
				TiXmlElement* positionY = light->FirstChildElement("PositionY");
				TiXmlElement* intensity = light->FirstChildElement("Intensity");
				TiXmlElement* radius = light->FirstChildElement("Radius");

				//Light pointLight;

				//if(colorR && positionX && positionY && intensity && radius)
				//{
				//	unsigned int red = atoi(colorR->GetText());
				//	unsigned int green = atoi(colorG->GetText());
				//	unsigned int blue = atoi(colorB->GetText());

				//	int posX = atoi(positionX->GetText());
				//	int posY = atoi(positionY->GetText());
				//	float lightIntensity = (float)atof(intensity->GetText());
				//	int lightRadius = atoi(radius->GetText());

				//	//CREATE THE LIGHT HERE
				//	pointLight.SetLightColor(red,green,blue);

				//	pointLight.position[0] = (float)posX;
				//	pointLight.position[1] = (float)posY;


				//	pointLight.intensity = lightIntensity;
				//	
				//	pointLight.radius[0] = (float)lightRadius;
				//	pointLight.radius[1] = (float)lightRadius;
				//	
				//	this->lights.push_back(pointLight);
				//}

				light = light->NextSiblingElement("Light");
			}
		}

		TiXmlElement* ambientLight = lightLayer->FirstChildElement("AmbientLight");

		if(ambientLight)
		{
			TiXmlElement* R = ambientLight->FirstChildElement("R");
			TiXmlElement* G = ambientLight->FirstChildElement("G");
			TiXmlElement* B = ambientLight->FirstChildElement("B");
			TiXmlElement* intensity = ambientLight->FirstChildElement("Intensity");

			//if(R && G && B && intensity)
			//{
			//	float red = (float)atof(R->GetText());
			//	float green = (float)atof(G->GetText());
			//	float blue = (float)atof(B->GetText());
			//	float lightIntensity = (float)atof(intensity->GetText());

			//	//CREATE THE AMBIENT LIGHT HERE
			//	this->ambientLight.SetLightColor(red,green,blue);
			//	this->ambientLight.intensity = lightIntensity;
			//}
		}
	}

	TiXmlElement* nextLevel = root->FirstChildElement("NextLevel");

	if(nextLevel)
	{
		TiXmlElement* fileName = nextLevel->FirstChildElement("FileName");

		//if(fileName)
		//{
		//	nextLevelFilename = fileName->GetText();
		//}
	}

	return true;
}